package com.fr71.project.dm.controller;

import com.fr71.common.utils.DateUtils;
import com.fr71.framework.web.domain.AjaxResult;
import com.fr71.project.dm.domain.PdPluginErr;
import com.fr71.project.dm.domain.PdUser;
import com.fr71.project.dm.service.IPdUserService;
import com.fr71.project.dm.service.IPublicService;
import com.fr71.project.dm.utils.DMUtils;
import com.fr71.project.monitor.service.ISysOperLogService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Api(tags = {"对外接口"})
@ApiSort(1)
@RestController
@RequestMapping("/open")
public class PublicController {

    @Autowired
    private IPublicService iPublicService;

    @Autowired
    private IPdUserService iPdUserService;

    @Autowired
    private ISysOperLogService iSysOperLogService;

    @GetMapping("/getLastDayData/{data}")
    public String getLastDayData(@PathVariable("data") String data) {
        if (!"pd2025".equals(data)) return "未授权";

        List<PdUser> totalList = iPdUserService.selectPdUserList(null);
        List<PdUser> lastList = totalList.stream()
                .filter(user -> DateUtils.isSameDay(user.getAuthStartTime(), DateUtils.addDays(new Date(), -1)))
                .collect(java.util.stream.Collectors.toList());

        Map<String, List<PdUser>> lastList2 = lastList.stream()
                .collect(java.util.stream.Collectors.groupingBy(PdUser::getBindIp));

        List<PdUser> lastUpdateListTemp = totalList.stream()
                .filter(user -> user.getUpdateTime() != null && 
                        !lastList.contains(user) && 
                        DateUtils.isSameDay(user.getUpdateTime(), DateUtils.addDays(new Date(), -1)))
                .collect(java.util.stream.Collectors.toList());
        
        Map<String, List<PdUser>> lastUpdateList = lastUpdateListTemp.stream()
                .collect(java.util.stream.Collectors.groupingBy(PdUser::getBindIp));

        String tip = "";

        if (!lastList2.isEmpty()) {
            tip = "\n昨日新增数据如下：\n";
            int index = 0;
            for (Map.Entry<String, List<PdUser>> entry : lastList2.entrySet()) {
                String bindIp = entry.getKey();
                List<PdUser> list = entry.getValue();
                index += 1;
                tip += "======【用户" + index + "开始】======\n";
                tip += "IP：" + bindIp + "\n";
                for (PdUser user : list) {
                    tip += (user.getUType() == 0 ? "工具箱" : "插件") +
                            "授权" + DateUtils.differentDaysByMillisecond(user.getAuthEndTime(), user.getAuthStartTime()) + 
                            "天（" + (user.getRemark() == null || user.getRemark().isEmpty() ? "普通用户" : user.getRemark()) + "）\n";
                }
                tip += "======【用户" + index + "结束】======\n";
            }
        }

        return "\n\n截止当日用户数量：" + totalList.stream().collect(java.util.stream.Collectors.groupingBy(PdUser::getBindIp)).size() + "\n" +
                "昨日改动用户数量：" + lastUpdateList.size() + "\n" +
                "昨日新增用户数量：" + lastList2.size() + "\n" +
                tip + "\n";
    }

    /**
     * 上报架设时长
     */
    @PostMapping("/uploadInstallTime")
    public AjaxResult uploadInstallTime(HttpServletRequest httpServletRequest, @RequestBody HashMap<String, Long> map) {
        return iPublicService.uploadInstallTime(DMUtils.getRealIp(httpServletRequest), map.get("time"));
    }

    /**
     * 授权查询
     * [uType] 0工具箱 1插件
     */
    @ApiOperation(value = "授权查询", notes = "授权验证，根据请求的IP和用户类型参数自动完成授权验证", httpMethod = "GET")
    @ApiOperationSupport(order = 1)
    @GetMapping("/checkAuth/{uType}")
    public AjaxResult checkAuth(
            HttpServletRequest httpServletRequest,
            @PathVariable("uType") @ApiParam(value = "用户类型", required = true) Integer uType) {
        return iPublicService.checkAuth(DMUtils.getRealIp(httpServletRequest), uType, "v1.0.0");
    }

    /**
     * 授权查询
     * [uType] 0工具箱 1插件
     */
    @ApiOperation(value = "授权查询", notes = "授权验证，根据请求的IP和用户类型参数自动完成授权验证", httpMethod = "GET")
    @ApiOperationSupport(order = 1)
    @GetMapping("/checkAuth/{uType}/{version}")
    public AjaxResult checkAuth2(
            HttpServletRequest httpServletRequest,
            @PathVariable("uType") @ApiParam(value = "用户类型", required = true) Integer uType,
            @PathVariable("version") @ApiParam(value = "版本号", required = true) String version) {
        return iPublicService.checkAuth(DMUtils.getRealIp(httpServletRequest), uType, version);
    }

    /**
     * 外部获取外网地址使用
     */
    @ApiOperation(value = "外部获取外网地址使用")
    @ApiOperationSupport(order = 2)
    @RequestMapping("/ip138")
    public String ip138(HttpServletRequest httpServletRequest) {
        return DMUtils.getRealIp(httpServletRequest);
    }

    /**
     * 根据安全码查询绑定的IP和到期时间
     */
    @ApiOperation(value = "根据安全码查询绑定的IP和到期时间")
    @ApiOperationSupport(order = 3)
    @PostMapping("/getSCodeInfo")
    public AjaxResult getSCodeInfo(@RequestBody Map<String, String> req) {
        return iPublicService.getSCodeInfo(req.get("sCode"));
    }

    /**
     * 根据安全码换绑IP
     */
    @ApiOperation(value = "根据安全码换绑IP")
    @ApiOperationSupport(order = 4)
    @PostMapping("/changeBindIpBySCode")
    public AjaxResult changeBindIpBySCode(HttpServletRequest httpServletRequest, @RequestBody Map<String, String> req) {
        Integer type = Integer.valueOf(req.get("type"));
        String newIp = type == 1 ? req.get("newIp") : DMUtils.getRealIp(httpServletRequest);

        if (newIp == null) {
            return AjaxResult.error("换绑失败");
        }

        return iPublicService.changeBindIpBySCode(newIp, req.get("sCode"), type);
    }

    /**
     * 领取体验卡
     */
    @ApiOperation(value = "领取体验卡")
    @ApiOperationSupport(order = 4)
    @PostMapping("/getTryCode")
    public AjaxResult getTryCode(HttpServletRequest httpServletRequest, @RequestBody Map<String, String> req) {
        return iPublicService.getTryScode(req.get("code"), req.get("ip"));
    }

    /**
     * 前端用来获取商品列表数据
     * @return {
     * dictLabel:名称
     * dictValue:价格
     * dictCode:付款编号
     * type:商品类型 0工具箱 1插件
     * }
     */
    @ApiOperation(value = "获取商品列表")
    @ApiOperationSupport(order = 5)
    @PostMapping("/listPrice")
    public AjaxResult listPrice() {
        return iPublicService.listPrice();
    }

    /**
     * 获取插件首页的数据
     */
    @ApiOperation(value = "插件获取首页数据")
     @GetMapping("/getHomeData")
    public AjaxResult getHomeData(HttpServletRequest httpServletRequest) {
        return iPublicService.getHomeData(DMUtils.getRealIp(httpServletRequest));
    }

    /**
     * 上传答题记录
     */
    @PostMapping("/uploadAsw")
    public AjaxResult uploadAsw(@RequestBody HashMap<String, Object> data, HttpServletRequest httpServletRequest) {
        return iPublicService.uploadAsw(data.get("asw"), data.get("aswTime"), DMUtils.getRealIp(httpServletRequest));
    }

    /**
     * 前端页面生成订单
     * [type] 商品类型 0工具箱 1插件
     * [priceCode] 付款编号
     * [buyType] 购买类型 buy 新购 add 续费
     * [sCode] 安全码 购买类型为新购时不用写，续费时必填
     * [bindIp] 绑定IP 购买类型为新购时必填，续费时不填
     * @return{
     * payUrl:付款url，用该url生成一个二维码展示
     * orderExpTime:订单有效期倒计时，单位秒，显示在二维码附近，到0时给二维码模糊处理，不让扫了,
     * orderId:订单号，在支付完成后的跳转成功页面使用该id查询订单状态
     * }
     */
    @ApiOperation(value = "生成订单")
    @ApiOperationSupport(order = 6)
    @PostMapping("/createOrder")
    public AjaxResult createOrder(@RequestBody Map<String, Object> req) {
        return iPublicService.createOrder(req);
    }

    /**
     * 查询订单信息
     * 付款成功后会自动跳转到支付成功的页面
     * 在支付成功页面使用订单号（生成订单接口返回）查询订单状态
     * [orderId] 订单号
     * @return {
     * 以下列出的字段需要显示在页面上
     * orderId:订单号
     * orderStatus:订单状态 0待支付 1已支付 2已过期 3支付失败
     * ip:授权IP
     *
     * authEndTime:有效期截止时间
     * sCode:安全码
     *
     * }
     */
    @ApiOperation(value = "查询订单信息")
    @ApiOperationSupport(order = 7)
    @GetMapping("/getOrderStatus/{orderId}")
    public AjaxResult getOrderStatus(@PathVariable("orderId") String orderId) {
        return iPublicService.getOrderStatus(orderId);
    }

    /**
     * 支付宝支付回调
     */
    @ApiOperation(value = "支付回调", hidden = true)
    @ApiOperationSupport(order = 7)
    @RequestMapping("/alipayResult")
    public String alipayResult(@RequestParam HashMap<String, String> allParams) {
        return iPublicService.alipayResult(allParams);
    }

    /**
     * 支付宝支付回调
     */
    @ApiOperation(value = "支付回调", hidden = true)
    @ApiOperationSupport(order = 7)
    @RequestMapping("/ltzfResult")
    public String ltzfResult(@RequestParam HashMap<String, String> allParams) {
        return iPublicService.ltzfResult(allParams);
    }

    /**
     * 微信支付回调
     */
    @ApiOperation(value = "支付回调", hidden = true)
    @ApiOperationSupport(order = 7)
    @RequestMapping("/wxpayResult")
    public String wxpayResult(
            @RequestHeader("Wechatpay-Nonce") String nonce,
            @RequestHeader("Wechatpay-Signature") String signature,
            @RequestHeader("Wechatpay-Timestamp") String timestamp,
            @RequestHeader("Wechatpay-Serial") String serial,
            @RequestBody String body) {
        return iPublicService.wxpayResult(nonce, signature, timestamp, serial, body);
    }

    /**
     * 获取版本号
     */
    @ApiOperation(value = "获取版本号", hidden = true)
    @ApiOperationSupport(order = 8)
    @GetMapping("/getVersionInfos")
    public AjaxResult getVersionInfos() {
        return iPublicService.getVersionInfos();
    }

    /**
     * 更新版本信息
     */
    @ApiOperation(value = "更新版本信息", hidden = true)
    @ApiOperationSupport(order = 9)
    @PostMapping("/setVersionInfos")
    public AjaxResult setVersionInfos(@RequestBody List<HashMap<String, Object>> list) {
        return iPublicService.setVersionInfos(list);
    }

    /**
     * app端调用 获取版本信息
     */
    @ApiOperation(value = "获取版本信息")
    @ApiOperationSupport(order = 10)
    @GetMapping("/getVersionInfoByType/{type}")
    public AjaxResult getVersionInfoByType(@PathVariable("type") Integer type) {
        return iPublicService.getVersionInfoByType(type);
    }

    /**
     * 获取公告
     */
    @ApiOperation(value = "获取公告", hidden = true)
    @ApiOperationSupport(order = 11)
    @GetMapping("/getNoticeList")
    public AjaxResult getNoticeList() {
        return iPublicService.getNoticeList();
    }

    /**
     * 更新公告
     */
    @ApiOperation(value = "更新公告", hidden = true)
    @ApiOperationSupport(order = 12)
    @PostMapping("/setNoticesList")
    public AjaxResult setNoticesList(@RequestBody List<HashMap<String, Object>> list) {
        return iPublicService.setNoticesList(list);
    }

    /**
     * app端调用 获取公告
     */
    @ApiOperation(value = "获取公告")
    @ApiOperationSupport(order = 13)
    @GetMapping("/getNoticeByType/{type}")
    public AjaxResult getNoticeByType(@PathVariable("type") Integer type) {
        return iPublicService.getNoticeByType(type);
    }

    /**
     * ip: String,//架设的服务器IP，可能为手动输入的虚拟机ip
     * reqIp: String,//请求的IP，用来检查授权信息
     * serverName: String,//区组名称
     * lineBaseName: String,//线路名称
     * portAaa: Int,//验证端口
     * lineNumber: Int,//线路数量
     * mysqlPsw: String,//数据库密码
     */
    @ApiOperation(value = "架设")
    @ApiOperationSupport(order = 14)
    @PostMapping("/doInstall")
    public AjaxResult doInstall(@RequestBody HashMap<String, Object> data, HttpServletRequest httpServletRequest) {
        return iPublicService.doInstall(
                data.get("ip").toString(),
                DMUtils.getRealIp(httpServletRequest),
                data.get("serverName").toString(),
                data.get("lineBaseName").toString(),
                Integer.valueOf(data.get("portAaa").toString()),
                Integer.valueOf(data.get("lineNumber").toString()),
                data.get("mysqlPsw").toString()
        );
    }

    /**
     * 获取bat
     */
    @ApiOperation(value = "生成bat登录器")
    @ApiOperationSupport(order = 15)
    @PostMapping("/getBat")
    public AjaxResult getBat(@RequestBody HashMap<String, Object> data, HttpServletRequest httpServletRequest) {
        return iPublicService.getBat(
                DMUtils.getRealIp(httpServletRequest),
                data.get("serverName").toString(),
                Integer.valueOf(data.get("port").toString())
        );
    }

    /**
     * 绑定qq
     */
    @ApiOperation(value = "绑定qq")
    @ApiOperationSupport(order = 16)
    @PostMapping("/bindQQ/{qq}/{type}")
    public AjaxResult bindQQ(
            @PathVariable("qq") String qq,
            @PathVariable("type") Integer type,
            HttpServletRequest httpServletRequest) {
        return iPublicService.bindQQ(qq, type, DMUtils.getRealIp(httpServletRequest));
    }

    /**
     * 上报插件错误异常
     */
    @ApiOperation(value = "上报插件错误异常")
    @ApiOperationSupport(order = 17)
    @PostMapping("/postPluginErr")
    public AjaxResult postPluginErr(@RequestBody PdPluginErr pdPluginErr, HttpServletRequest httpServletRequest) {
        return iPublicService.postPluginErr(pdPluginErr, DMUtils.getRealIp(httpServletRequest));
    }

    /**
     * 设置新的二级密码
     */
    @ApiOperation(value = "设置新的二级密码")
    @ApiOperationSupport(order = 18)
    @PostMapping("/setNewPsw/{sCode}/{newPwd}")
    public AjaxResult setNewPsw(@PathVariable("sCode") String sCode, @PathVariable("newPwd") String newPwd) {
        return iPublicService.setNewPsw(sCode, newPwd);
    }

    /**
     * 上报事件
     */
    @PostMapping("/uploadEvent")
    public AjaxResult uploadEvent(@RequestBody HashMap<String, Object> data) {
        return iPublicService.uploadEvent(data);
    }

    /**
     * 根据qq查询绑定的工具箱或插件的有效期
     */
    @GetMapping("/getInfoByQQ/{qq}")
    public String getInfoByQQ(@PathVariable("qq") String qq) {
        return iPublicService.getInfoByQQ(qq);
    }

    /**
     * 使用QQ签到
     */
    @PostMapping("/doSignByQQ/{qq}")
    public String doSignByQQ(@PathVariable("qq") String qq) {
        return iPublicService.doSignByQQ(qq);
    }
}